/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
float ADC_Vol;
/* USER CODE END Variables */
/* Definitions for Task_ADC */
osThreadId_t Task_ADCHandle;
const osThreadAttr_t Task_ADC_attributes = {
  .name = "Task_ADC",
  .stack_size = 1024 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for Task_Info */
osThreadId_t Task_InfoHandle;
const osThreadAttr_t Task_Info_attributes = {
  .name = "Task_Info",
  .stack_size = 1024 * 4,
  .priority = (osPriority_t) osPriorityLow,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void APPTask_ADC(void *argument);
void APPTask_Info(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
    /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
    /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
    /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
    /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of Task_ADC */
  Task_ADCHandle = osThreadNew(APPTask_ADC, NULL, &Task_ADC_attributes);

  /* creation of Task_Info */
  Task_InfoHandle = osThreadNew(APPTask_Info, NULL, &Task_Info_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
    /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
    /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_APPTask_ADC */
/**
  * @brief  Function implementing the Task_ADC thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_APPTask_ADC */
void APPTask_ADC(void *argument)
{
  /* USER CODE BEGIN APPTask_ADC */
    TickType_t pxPreviousWakeTime = xTaskGetTickCount();
    float ADC_Vol;
//    OLED_ShowString(0, 0 + 2, "ADC_value = ", 12, 0);
    /* Infinite loop */
#if 0
    for (;;) {
        HAL_ADC_Start(&hadc1);
        if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) {
            float value = HAL_ADC_GetValue(&hadc1);
            float voltage = value * 3.3 / 4096;

            uint8_t temp_str[100];
            sprintf(temp_str, "ADC Value(mv) = %f", voltage);
            printf("%s\n", temp_str);
            printf("Wake Time: %d\n", pxPreviousWakeTime);
            OLED_ShowString(0, 0 + 2, temp_str, 12, 0);

        }
        vTaskDelayUntil(&pxPreviousWakeTime, pdMS_TO_TICKS(500));
    }
#endif

#if 1
    for(;;) {
        HAL_ADC_Start(&hadc1);
        if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) {
            float adcValue = HAL_ADC_GetValue(&hadc1);
            ADC_Vol = adcValue / 4096.0 * 3.3;
            uint8_t temp_str[100];
            sprintf(temp_str, "ADC Value(mv) = %f", ADC_Vol);
            printf("%s\n", temp_str);
            printf("Wake Time: %d\n", pxPreviousWakeTime);
            OLED_ShowString(0, 0 + 2, temp_str, 12, 0);
        }
        vTaskDelayUntil(&pxPreviousWakeTime, pdMS_TO_TICKS(500));
//        vTaskDelay(pdMS_TO_TICKS(500));
    }
#endif

#if 0
    for(;;) {

        vTaskDelayUntil(&pxPreviousWakeTime, pdMS_TO_TICKS(500));

    }
#endif

  /* USER CODE END APPTask_ADC */
}

/* USER CODE BEGIN Header_APPTask_Info */
/**
* @brief Function implementing the Task_Info thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_APPTask_Info */
void APPTask_Info(void *argument)
{
  /* USER CODE BEGIN APPTask_Info */
    TaskHandle_t taskHandle = Task_ADCHandle;
    TaskStatus_t taskInfo;
    BaseType_t getFreeStackSpace = pdTRUE;
    eTaskState taskState = eInvalid;
    vTaskGetInfo(taskHandle, &taskInfo, getFreeStackSpace, taskState);

    taskENTER_CRITICAL();

    uint8_t temp_str[40];
    sprintf(temp_str, "Task Name = %s", taskInfo.pcTaskName);
//    OLED_ShowString(0, 0 + 4, temp_str, 12, 0);
    printf("%s\n", temp_str);

    sprintf(temp_str, "Task Number = %d", taskInfo.xTaskNumber);
    printf("%s\n", temp_str);

    sprintf(temp_str, "Task State = %d", taskInfo.eCurrentState);
    printf("%s\n", temp_str);

    sprintf(temp_str, "Task Priority = %d", taskInfo.uxCurrentPriority);
    printf("%s\n", temp_str);

    sprintf(temp_str, "Stack High Water Mark = %d(Word)", taskInfo.usStackHighWaterMark);
    printf("%s\n", temp_str);

    //--------



    taskHandle = xTaskGetIdleTaskHandle();
    sprintf(temp_str, "Idle Task = %d", uxTaskGetStackHighWaterMark(taskHandle));
    printf("%s\n", temp_str);

    sprintf(temp_str, "Task_ADC = %d", uxTaskGetStackHighWaterMark(Task_ADCHandle));
    printf("%s\n", temp_str);

    sprintf(temp_str, "Task_Info = %d", uxTaskGetStackHighWaterMark(Task_InfoHandle));
    printf("%s\n", temp_str);

    //------------



    sprintf(temp_str, "uxTaskGetNumberOfTasks() = %d", uxTaskGetNumberOfTasks());
    printf("%s\n", temp_str);
//    printf("%s\n", temp_str);
//
//    sprintf(temp_str, "Task State = %d", taskInfo.eCurrentState);
//    printf("%s\n", temp_str);
    char pcWriteBuffer[300];
    vTaskList(pcWriteBuffer);

    taskEXIT_CRITICAL();
    /* Infinite loop */
    for (;;) {

        osDelay(1);
    }

    vTaskDelete(NULL);
  /* USER CODE END APPTask_Info */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

